/*
 * msgcli.c
 * 
 * Copyright 2012 Kamil Cukrowski <kamil@dyzio.pl>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 */
#define MSGCLI_VERSION "0.0.2"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <arpa/inet.h>
#include "libs/msgserv.h"

#define MAX_MESSAGES 200
#define DEFAULT_PRI 10
#define MY_NAME "msgcli"
#define PINFO(smt, ...) do { printf(smt, ## __VA_ARGS__ ); printf("\n"); } while(0)
#define PDEBUG(str, ...) PDEBUGL(1, str, ##__VA_ARGS__);
#define PDEBUGL(x, str, ...) do{ if ( debug >= x ) _INTERNAL_LOGIT(str, ##__VA_ARGS__); }while(0)
#define PERROR(str, ...) do { printf(MY_NAME ": (%s:%s:%d): ", __FILE__, __FUNCTION__, __LINE__); printf(str, ##__VA_ARGS__); printf("error %d:%s \n", errno, strerror(errno)); }while(0)
#define _INTERNAL_LOGIT(str, ...) do { printf( MY_NAME ": (%s:%s:%d): ", __FILE__, __FUNCTION__, __LINE__); printf(str, ##__VA_ARGS__); printf("\n"); }while(0)

in_addr_t server_ip =  { 16777343 }; // 127.0.0.1
int debug = 1;

int timeout = 10;
int messages = 0;

int sockfd;
char **msg;
int *msg_len;

/* --------- safe exit and sig hup and fatal ------------- */

static void safe_exit()
{
	int i;
	msglcd_send(sockfd, MSGLCD_MESG_ERROR, MSGLCD_MESG_LENGTH);
	for (i = 0; i < messages; ++i)
		free(msg[i]);
	free(msg);
	free(msg_len);
	exit(0);
}

#define fatal(mesg, ...) \
do {\
	printf(mesg" : %d %s \n", ##__VA_ARGS__, errno, strerror(errno));\
	safe_exit();\
} while (0)

static void sig_hup ()
{
	printf("Cought signal. Shutting down.\n");
	safe_exit();
}

static void add_message(char *pnt)
{
	int len = strlen(pnt);
	if ( len <= 0 )
		return;
	
	msg = realloc(msg, (messages+1)*sizeof(*msg));
	if ( !msg ) fatal("error allocating memory msg ");
	
	msg_len = realloc(msg_len, (messages+1)*sizeof(*msg_len));
	if ( !msg_len ) fatal("error allocating memory msg_len ");
	
	msg[messages] = realloc(msg[messages], (msg_len[messages]+len)*sizeof(**msg));
	if ( !msg[messages] ) fatal("error allocating memory msg[messaes) ");
	
	strcpy(msg[messages]+msg_len[messages], pnt);
	msg_len[messages] += len;
	messages++;
}

static void parse_cmd(int argc, char *argv[])
{
	extern char *optarg;
	
	int c = 0;
	while ( (c = getopt(argc, argv, "hm:dsi:t:")) != -1 ) {
		switch (c) {
		case 'h':
		case '?':
			printf("msgcli: messaging system to LCD geteway.\n"
				"Usage: msgcli [hm:dsi:] [message [next message...]]\n"
				"\t-m\tnew massage to add;\n"
				"\t-h\tdisplay this help;\n"
				"\t-d\tdebug monde on;\n"
				"\t-s\tsilent (do not print anything);\n"
				"\t-i<IP address>\t server ip address;\n"
				"\t-t<timeout>\tset refresh timeout default:%d\n"
				"\n"
				"Example: msgcli \"ala\" -> adds message with text ala and priority 1 \n"
				"Example: msgcli \"#03#baba\" -> add message with text baba and priority 3 \n"
				,
				timeout
				);
			exit(0);
		case 'm':
			add_message(optarg);
			break;
		case 'i':
			server_ip = inet_addr(optarg);
			break;
		case 't':
			timeout = atoll(optarg);
			break;
		case 'd':			debug++;
			break;
		case 's':
			debug = 0;
			break;
		default:
			break;
		}
	}
	
	for (; optind < argc; optind++ )
		add_message(argv[optind]);
	
	if ( !messages )
		fatal("No messages to display given ");
	if ( timeout < 0 )
		fatal("Negative timeout!");
}

static void handle_msglcd_handle_server(const int lcd_sock) 
{
	int i;
	i = msglcd_handle_server(lcd_sock);
	switch ( i ) {
	case -5:
	case -1:
		fatal("Strange error occured %d ", i);
	case -4:
		fatal("Server closed the connection. %d ", i);
	case -6:
		fatal("server sended error messege %d", i);
	case -2:
		fatal("Server closed the connection without sending exit mesg. %d ", i);
	case -3:
		fatal("my mesg has somth wrong %d ", i);
	default:
		PDEBUG("msglcd_handle_server %d ", i);
	}
}

static int wait_for_any_message()
{
	fd_set set;
	struct timeval tv;
	int ret;
	
	for(;;) {
		FD_ZERO(&set);
		FD_SET(sockfd,&set);
		tv.tv_sec = 100;  /* well, we get stuck here */
		tv.tv_usec = 0;
		ret = select ( sockfd+1,&set,NULL,NULL,&tv );
		if (ret > 0) {
			return ret;
		} else if (ret == -1 && errno != EINTR) {
				return -1;
		}
		PDEBUG("waited for some seconds. nothing");
	}
	return 1; /* ;) */
}

int main(int argc, char *argv[])
{
	int i, ret;
	
	parse_cmd(argc,argv);
	
	signal(SIGHUP,sig_hup);
	signal(SIGQUIT,sig_hup);
	signal(SIGTERM,sig_hup);
	signal(SIGINT,sig_hup);
	
	sockfd = msglcd_connect_client(server_ip);
	if ( sockfd < 0 )
		fatal("connect");
	PDEBUG("Connected.");
	
	for (;;) {
		
		for (i = 0; i < messages; i++) {
			
			if ( msg[i][0] == '#' && msg[i][3] == '#' ) {
				PDEBUG("msg[%d]: pri:%d len:%d - mesg:%s", i, atoi(&(msg[i][1])), msg_len[i]-4, msg[i]+4);
				ret = msglcd_updat(sockfd, i, atoi(&(msg[i][1])), msg[i]+4, msg_len[i]-4);
			} else {
				PDEBUG("msg[%d]: def_pri:%d len:%d - mesg:%s", i, DEFAULT_PRI, msg_len[i], msg[i]);
				ret = msglcd_updat(sockfd, i, DEFAULT_PRI, msg[i], msg_len[i]);
			}
			
			if ( ret < 0 )
				fatal("erro updating mesg %d - ", ret);
			
			handle_msglcd_handle_server(sockfd);
		}
		
		sleep(timeout);
		/* for ( ;; ) {
			i = handle_msglcd_handle_server(sockfd);
			if ( i == 0 )
				break;
			if ( i < 0 )
				fatal("shit?");
		}
		ret = wait_for_any_message();
		PDEBUG("wait for any message %d \n", ret);
		handle_msglcd_handle_server(sockfd);*/
	}
	
	return(0);
}

